﻿/// <reference path="../devextreme/ts/jquery.d.ts" />
/// <reference path="../devextreme/ts/dx.all.d.ts" />

($ => {
    class VideoListEditor {
        constructor(options) {
            this.options = options;
            this.videos = [];

            this.init();
        }

        get selectedVideos() {
            return this.videos.filter(video => video.selected);
        }

        init() {
            this.$editor = this.createVideoListEditor();
            this.scrollView = this.$editor.dxScrollView('instance');
            this.$videoList = this.$editor.find('.dx-scrollview-content');
            this.$editor.find('.dx-scrollable-content').on('click', e => {
                if (e.target.classList.contains('dx-scrollview-content') || e.target.classList.contains('dx-scrollable-content')) {
                    this.clearSelection();
                }
            });
        }

        getVideosByIds(videoIds) {
            if (this.options.onGetVideosByIds instanceof Function) {
                return this.options.onGetVideosByIds(videoIds) ?? [];
            }
            return [];
        }

        addVideo(video) {
            if (this.videos.findIndex(item => item.id === video.id) < 0) {
                this.videos.push(video);
            }
            this.$videoList.append(this.createVideoElement(video));
            this.scrollView.update();
        }

        clearVideos() {
            this._currentVideo = null;
            this.$videoList.empty();
            this.scrollView.update();
        }

        selectVideo(video) {
            video.selected = true;
            this.getVideoElement(video)?.addClass('selected');
        }

        selectVideos(videos) {
            for (const video of videos) {
                this.selectVideo(video);
            }
        }

        selectVideosByIndex(startIndex, endIndex) {
            if (startIndex > endIndex) {
                [startIndex, endIndex] = [endIndex - 1, startIndex + 1];
            }
            const videos = this.videos.slice(startIndex, endIndex);
            this.clearSelection();
            this.selectVideos(videos);
        }

        unselectVideo(video) {
            video.selected = false;
            this.getVideoElement(video)?.removeClass('selected');
        }

        invertSelect() {
            for (const video of this.videos) {
                if (video.selected) {
                    this.unselectVideo(video);
                } else {
                    this.selectVideo(video);
                }
            }
        }

        selectAll() {
            for (const video of this.videos) {
                this.selectVideo(video);
            }
        }

        clearSelection() {
            for (const video of this.videos) {
                this.unselectVideo(video);
            }
        }

        createVideoElement(video) {
            if (this.options.onCreateVideoElement instanceof Function) {
                const videoId = video.id;
                const $video = this.options.onCreateVideoElement(video);
                $video.on('click', (e) => {
                    const video = this.videos.find(i => i.id === videoId);
                    if (video) {
                        if (e.shiftKey) {
                            const startIndex = this.videos.findIndex(x => x.selected);
                            const endIndex = this.videos.findIndex(x => x.id === videoId);
                            this.selectVideosByIndex(startIndex, endIndex + 1);
                        } else if (e.ctrlKey) {
                            if (video.selected) {
                                this.unselectVideo(video);
                            } else {
                                this.selectVideo(video);
                            }
                        } else {
                            this.clearSelection();
                            this.selectVideo(video);
                        }
                    }
                });
                $video.on('dblclick', () => {
                    if (this.options.onVideoDoubleClicked instanceof Function) {
                        const video = this.videos.find(i => i.id === videoId);
                        this.options.onVideoDoubleClicked(video);
                    }
                });
                this.$videoList.append($video);
            }
        }

        getVideoElement(video) {
            if (this.options.onGetVideoElement instanceof Function) {
                return this.options.onGetVideoElement(video);
            }
        }

        refresh() {
            if (this.options.onGetVideos instanceof Function) {
                this.clearVideos();
                const $loadPanelContainer = $('<div />').appendTo(this.$editor);
                const loadPanel = $loadPanelContainer.dxLoadPanel({
                    shading: true,
                    position: {
                        of: this.$editor
                    }
                }).dxLoadPanel('instance');
                loadPanel.show();
                this.options.onGetVideos().then(videos => {
                    this.videos = videos;
                    for (const video of videos) {
                        this.addVideo(video);
                    }
                    if (this.options.onRefreshVideoInfos instanceof Function) {
                        this.options.onRefreshVideoInfos();
                    }
                }).finally(() => {
                    loadPanel.dispose();
                });
            }
        }

        createVideoListEditor() {
            return $(`<div class="video-list-editor" />`).dxScrollView({
                showScrollbar: 'always',
            });
        }
    }

    class VideoList {
        constructor(options) {
            this.options = options;
            this.init();
        }

        get videos() {
            return this.videoListEditor.videos;
        }

        init() {
            if (this.options.container) {
                this.videoListEditor = new VideoListEditor({
                    ...this.options,
                    onCreateVideoElement: this.createVideoElement.bind(this),
                    onGetVideoElement: this.getVideoElement.bind(this),
                    onRefreshVideoInfos: this.refreshVideoNumber.bind(this),
                    onVideoDoubleClicked: (video) => this.viewVideo(video)
                });
                $(this.options.container).append(this.createToolbar()).append(this.videoListEditor.$editor);
            }
        }

        createVideoElement(video) {
            const videoId = video.id;
            const videoTitle = `${video.date}`;
            const $videoItem = $(`<div class="video-item video-item-${videoId}" video-id="${videoId}" title="${videoTitle}" />`);

            const $video = $(`<div class="video" />`);

            $videoItem.append($video);

            const $videoNumber = $('<div class="video-number" />');
            $videoNumber.text(this.videos.findIndex(x => x.id === video.id) + 1);
            $videoItem.append($videoNumber);

            const $videoSize = $('<div class="video-size" />');
            $videoSize.text(video.size);
            $videoItem.append($videoSize);

            const $videoDuration = $('<div class="video-duration" />');
            $videoDuration.text(video.duration);
            $videoItem.append($videoDuration);

            return $videoItem;
        }

        getVideoElement(video) {
            return this.videoListEditor.$videoList.find(`.video-item-${video.id}`);
        }

        viewVideo(video) {
            if (this.options.onViewVideo instanceof Function) {
                this.options.onViewVideo(video);
            }
        }

        viewSelectedVideo() {
            if (this.videoListEditor.selectedVideos.length > 0) {
                this.viewVideo(this.videoListEditor.selectedVideos[0]);
            }
        }

        importVideos() {
            if (this.options.onImportVideos instanceof Function) {
                this.options.onImportVideos().then(() => {
                    this.videoListEditor.refresh();
                });
            }
        }

        exportSelectedVideos() {
            if (this.options.onExportVideos instanceof Function) {
                this.options.onExportVideos(this.videoListEditor.selectedVideos);
            }
        }

        deleteVideos(videos) {
            videos ??= [];
            if (videos.length > 0) {
                if (this.options.onDeleteVideos instanceof Function) {
                    DevExpress.ui.dialog.confirm('是否要删除所选择的视频?', '删除').done(result => {
                        if (result) {
                            this.options.onDeleteVideos(videos).then(() => {
                                this.videoListEditor.refresh();
                            });
                        }
                    });
                }
            }
        };

        deleteSelectedVideos() {
            this.deleteVideos(this.videoListEditor.selectedVideos);
        }

        refreshVideoNumber() {
            this.videoListEditor.$videoList.find('.video-number').each((index, element) => {
                $(element).text(index + 1);
            });
        }

        createToolbar() {
            this.$toolbar = $('<div class="video-list-toolbar" />').dxToolbar({
                multiline: true,
                items: [{
                    location: 'before',
                    widget: 'dxButton',
                    options: {
                        text: '打开',
                        icon: 'folder',
                        beginGroup: true,
                        onClick: () => {
                            this.viewSelectedVideo();
                        },
                    },
                }, {
                    location: 'before',
                    widget: 'dxButton',
                    options: {
                        text: '导入',
                        icon: 'import',
                        onClick: () => {
                            this.importVideos();
                        },
                    },
                }, {
                    location: 'before',
                    widget: 'dxButton',
                    options: {
                        text: '导出',
                        icon: 'export',
                        beginGroup: true,
                        onClick: () => {
                            this.exportSelectedVideos();
                        },
                    },
                }, {
                    location: 'before',
                    widget: 'dxButton',
                    options: {
                        text: '删除',
                        icon: 'remove',
                        beginGroup: true,
                        onClick: () => {
                            this.deleteSelectedVideos();
                        },
                    },
                }, {
                    location: 'before',
                    widget: 'dxDropDownButton',
                    options: {
                        text: '选择',
                        icon: 'check',
                        dropDownOptions: {
                            width: 150,
                        },
                        items: [
                            {
                                text: '全部选择',
                                icon: 'selectall',
                                onClick: () => {
                                    this.videoListEditor.selectAll();
                                },
                            }, {
                                text: '反向选择',
                                icon: 'unselectall',
                                onClick: () => {
                                    this.videoListEditor.invertSelect();
                                },
                            }, {
                                text: '取消选择',
                                icon: 'clear',
                                onClick: () => {
                                    this.videoListEditor.clearSelection();
                                },
                            },
                        ],
                    },
                }, {
                    location: 'after',
                    widget: 'dxButton',
                    options: {
                        text: '刷新',
                        icon: 'refresh',
                        onClick: () => {
                            this.videoListEditor.refresh();
                        },
                    },
                }],
            });
            return this.$toolbar;
        }

        setReadOnly(readOnly) {
            const toolbar = this.$toolbar.dxToolbar('instance');
            const tools = toolbar.option('items');
            for (const tool of tools) {
                if (tool.options?.text === '导入' || tool.options?.text === '删除') {
                    tool.visible = !readOnly;
                }
            }
            toolbar.repaint();
        }
    }

    $.fn.reportVideoList = function (options) {
        options = options || {};

        const $container = $(this[0]).addClass('video-list-main');
        const $videoList = $('<div class="video-list-container" />');

        const videoList = new VideoList({
            container: $videoList,
            onGetVideos: options.onGetVideos,
            onGetVideosByIds: videoIds => {
                return videoList.videos.filter(video => videoIds.indexOf(video.id) >= 0);
            },
            onDeleteVideos: videos => {
                if (options.onDeleteVideos instanceof Function) {
                    options.onDeleteVideos(videos).then(() => {
                        videoList.videoListEditor.refresh();
                    });
                }
            },
            ...options
        });

        $container.append($videoList);

        return {
            viewVideo: video => videoList.viewVideo(video),
            refresh: () => videoList.videoListEditor.refresh(),
            setReadOnly: readOnly => videoList.setReadOnly(readOnly),
        };
    }
})(jQuery);